package com.rickpan.service;

import com.rickpan.dto.request.CreateFolderRequest;
import com.rickpan.dto.request.MoveFolderRequest;
import com.rickpan.dto.request.RenameFolderRequest;
import com.rickpan.dto.response.FolderTreeNodeResponse;
import com.rickpan.dto.response.FolderPathResponse;
import com.rickpan.entity.FileInfo;
import com.rickpan.repository.FileInfoRepository;
import com.rickpan.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件夹服务类
 *
 * @author RickPan Team
 * @since 2025-07-02
 */
@Service
public class FolderService {

    @Autowired
    private FileInfoRepository fileInfoRepository;

    /**
     * 获取文件夹树
     *
     * @param userId 用户ID
     * @param parentId 父文件夹ID
     * @param depth 加载深度
     * @return 文件夹树节点列表
     */
    public List<FolderTreeNodeResponse> getFolderTree(Long userId, Long parentId, Integer depth) {
        System.out.println("获取文件夹树: userId=" + userId + ", parentId=" + parentId + ", depth=" + depth);

        // 查询指定父目录下的所有文件夹
        List<FileInfo> folders;
        if (parentId == null) {
            folders = fileInfoRepository.findRootFoldersByOwnerId(userId);
        } else {
            folders = fileInfoRepository.findFoldersByOwnerIdAndParentId(userId, parentId);
        }

        List<FolderTreeNodeResponse> result = new ArrayList<>();

        for (FileInfo folder : folders) {
            // 统计文件夹下的文件数量
            Integer fileCount = fileInfoRepository.countFilesByFolderId(userId, folder.getId());

            // 检查是否有子文件夹
            Boolean hasChildren = fileInfoRepository.hasSubFolders(userId, folder.getId());

            FolderTreeNodeResponse node = new FolderTreeNodeResponse(
                folder.getId(),
                folder.getOriginalName(),
                folder.getParentId(),
                fileCount,
                hasChildren,
                folder.getCreatedAt(),
                folder.getUpdatedAt()
            );

            // 如果需要加载子级且深度大于1，递归加载
            if (depth > 1 && hasChildren) {
                List<FolderTreeNodeResponse> children = getFolderTree(userId, folder.getId(), depth - 1);
                node.setChildren(children);
            }

            result.add(node);
        }

        return result;
    }

    /**
     * 创建文件夹
     *
     * @param userId 用户ID
     * @param request 创建请求
     * @return 创建的文件夹信息
     */
    @Transactional
    public FolderTreeNodeResponse createFolder(Long userId, CreateFolderRequest request) {
        System.out.println("创建文件夹: userId=" + userId + ", folderName=" + request.getName() + ", parentId=" + request.getParentId());

        // 验证父文件夹是否存在（如果指定了parentId）
        if (request.getParentId() != null) {
            Optional<FileInfo> parentFolder = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(request.getParentId(), userId);
            if (parentFolder.isEmpty() || !parentFolder.get().getIsDirectory()) {
                throw new BusinessException("父文件夹不存在或不是文件夹");
            }
        }

        // 检查同名文件夹是否已存在
        Optional<FileInfo> existingFolder;
        if (request.getParentId() == null) {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentIdIsNull(userId, request.getName());
        } else {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentId(userId, request.getName(), request.getParentId());
        }

        if (existingFolder.isPresent()) {
            throw new BusinessException("同名文件夹已存在");
        }

        // 创建文件夹实体
        FileInfo folder = new FileInfo();
        folder.setOwnerId(userId);
        folder.setOriginalName(request.getName());
        folder.setParentId(request.getParentId());
        folder.setIsDirectory(true);
        folder.setFileSize(0L);
        folder.setMimeType("folder");
        folder.setCreatedAt(LocalDateTime.now());
        folder.setUpdatedAt(LocalDateTime.now());
        folder.setIsDeleted(false);

        // 保存到数据库
        FileInfo savedFolder = fileInfoRepository.save(folder);

        System.out.println("文件夹创建成功: folderId=" + savedFolder.getId());

        return new FolderTreeNodeResponse(
            savedFolder.getId(),
            savedFolder.getOriginalName(),
            savedFolder.getParentId(),
            0,
            false,
            savedFolder.getCreatedAt(),
            savedFolder.getUpdatedAt()
        );
    }

    /**
     * 重命名文件夹
     *
     * @param userId 用户ID
     * @param folderId 文件夹ID
     * @param request 重命名请求
     * @return 更新后的文件夹信息
     */
    @Transactional
    public FolderTreeNodeResponse renameFolder(Long userId, Long folderId, RenameFolderRequest request) {
        System.out.println("重命名文件夹: userId=" + userId + ", folderId=" + folderId + ", newName=" + request.getName());

        // 验证文件夹是否存在
        Optional<FileInfo> folderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(folderId, userId);
        if (folderOpt.isEmpty() || !folderOpt.get().getIsDirectory()) {
            throw new BusinessException("文件夹不存在");
        }

        FileInfo folder = folderOpt.get();

        // 检查同名文件夹是否已存在（排除自己）
        Optional<FileInfo> existingFolder;
        if (folder.getParentId() == null) {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentIdIsNull(userId, request.getName());
        } else {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentId(userId, request.getName(), folder.getParentId());
        }

        if (existingFolder.isPresent() && !existingFolder.get().getId().equals(folderId)) {
            throw new BusinessException("同名文件夹已存在");
        }

        // 更新文件夹名称
        folder.setOriginalName(request.getName());
        folder.setUpdatedAt(LocalDateTime.now());

        FileInfo savedFolder = fileInfoRepository.save(folder);

        System.out.println("文件夹重命名成功: folderId=" + folderId + ", newName=" + request.getName());

        // 统计文件数量和子文件夹
        Integer fileCount = fileInfoRepository.countFilesByFolderId(userId, folderId);
        Boolean hasChildren = fileInfoRepository.hasSubFolders(userId, folderId);

        return new FolderTreeNodeResponse(
            savedFolder.getId(),
            savedFolder.getOriginalName(),
            savedFolder.getParentId(),
            fileCount,
            hasChildren,
            savedFolder.getCreatedAt(),
            savedFolder.getUpdatedAt()
        );
    }

    /**
     * 移动文件夹
     *
     * @param userId 用户ID
     * @param folderId 文件夹ID
     * @param request 移动请求
     */
    @Transactional
    public void moveFolder(Long userId, Long folderId, MoveFolderRequest request) {
        System.out.println("移动文件夹: userId=" + userId + ", folderId=" + folderId + ", targetParentId=" + request.getTargetParentId());

        // 验证源文件夹是否存在
        Optional<FileInfo> folderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(folderId, userId);
        if (folderOpt.isEmpty() || !folderOpt.get().getIsDirectory()) {
            throw new BusinessException("文件夹不存在");
        }

        FileInfo folder = folderOpt.get();

        // 验证目标父文件夹是否存在（如果指定了targetParentId）
        if (request.getTargetParentId() != null) {
            Optional<FileInfo> targetParent = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(request.getTargetParentId(), userId);
            if (targetParent.isEmpty() || !targetParent.get().getIsDirectory()) {
                throw new BusinessException("目标父文件夹不存在或不是文件夹");
            }

            // 检查是否试图移动到自己的子文件夹中（防止循环引用）
            if (isDescendantFolder(userId, request.getTargetParentId(), folderId)) {
                throw new BusinessException("不能将文件夹移动到自己的子文件夹中");
            }
        }

        // 检查目标位置是否已有同名文件夹
        Optional<FileInfo> existingFolder;
        if (request.getTargetParentId() == null) {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentIdIsNull(userId, folder.getOriginalName());
        } else {
            existingFolder = fileInfoRepository.findByOwnerIdAndNameAndParentId(userId, folder.getOriginalName(), request.getTargetParentId());
        }

        if (existingFolder.isPresent() && !existingFolder.get().getId().equals(folderId)) {
            throw new BusinessException("目标位置已存在同名文件夹");
        }

        // 更新文件夹的父ID
        folder.setParentId(request.getTargetParentId());
        folder.setUpdatedAt(LocalDateTime.now());

        fileInfoRepository.save(folder);

        System.out.println("文件夹移动成功: folderId=" + folderId + ", newParentId=" + request.getTargetParentId());
    }

    /**
     * 删除文件夹
     *
     * @param userId 用户ID
     * @param folderId 文件夹ID
     */
    @Transactional
    public void deleteFolder(Long userId, Long folderId) {
        System.out.println("删除文件夹: userId=" + userId + ", folderId=" + folderId);

        // 验证文件夹是否存在
        Optional<FileInfo> folderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(folderId, userId);
        if (folderOpt.isEmpty() || !folderOpt.get().getIsDirectory()) {
            throw new BusinessException("文件夹不存在");
        }

        FileInfo folder = folderOpt.get();

        // 检查文件夹是否为空
        Integer fileCount = fileInfoRepository.countFilesByFolderId(userId, folderId);
        Boolean hasSubFolders = fileInfoRepository.hasSubFolders(userId, folderId);

        if (fileCount > 0 || hasSubFolders) {
            throw new BusinessException("文件夹不为空，无法删除");
        }

        // 软删除文件夹（空文件夹不需要更新存储空间）
        folder.setIsDeleted(true);
        folder.setUpdatedAt(LocalDateTime.now());

        fileInfoRepository.save(folder);

        System.out.println("文件夹删除成功: folderId=" + folderId);
    }

    /**
     * 获取文件夹详情
     *
     * @param userId 用户ID
     * @param folderId 文件夹ID
     * @return 文件夹详情
     */
    public FolderTreeNodeResponse getFolderDetail(Long userId, Long folderId) {
        System.out.println("获取文件夹详情: userId=" + userId + ", folderId=" + folderId);

        Optional<FileInfo> folderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(folderId, userId);
        if (folderOpt.isEmpty() || !folderOpt.get().getIsDirectory()) {
            throw new BusinessException("文件夹不存在");
        }

        FileInfo folder = folderOpt.get();

        // 统计文件数量和子文件夹
        Integer fileCount = fileInfoRepository.countFilesByFolderId(userId, folderId);
        Boolean hasChildren = fileInfoRepository.hasSubFolders(userId, folderId);

        return new FolderTreeNodeResponse(
            folder.getId(),
            folder.getOriginalName(),
            folder.getParentId(),
            fileCount,
            hasChildren,
            folder.getCreatedAt(),
            folder.getUpdatedAt()
        );
    }

    /**
     * 获取文件夹路径
     *
     * @param userId 用户ID
     * @param folderId 文件夹ID
     * @return 文件夹路径信息
     */
    public FolderPathResponse getFolderPath(Long userId, Long folderId) {
        System.out.println("获取文件夹路径: userId=" + userId + ", folderId=" + folderId);

        List<FolderPathResponse.BreadcrumbItem> breadcrumbs = new ArrayList<>();
        StringBuilder pathBuilder = new StringBuilder();

        // 递归构建路径
        buildFolderPath(userId, folderId, breadcrumbs, pathBuilder);

        // 反转面包屑列表（因为是从叶子节点向根节点构建的）
        List<FolderPathResponse.BreadcrumbItem> reversedBreadcrumbs = breadcrumbs.stream()
                .collect(Collectors.toList());
        java.util.Collections.reverse(reversedBreadcrumbs);

        String path = pathBuilder.length() > 0 ? pathBuilder.toString() : "/";

        return new FolderPathResponse(path, reversedBreadcrumbs);
    }

    /**
     * 递归构建文件夹路径
     */
    private void buildFolderPath(Long userId, Long folderId,
                               List<FolderPathResponse.BreadcrumbItem> breadcrumbs,
                               StringBuilder pathBuilder) {
        if (folderId == null) {
            return;
        }

        Optional<FileInfo> folderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(folderId, userId);
        if (folderOpt.isEmpty()) {
            return;
        }

        FileInfo folder = folderOpt.get();

        // 添加当前文件夹到面包屑
        breadcrumbs.add(new FolderPathResponse.BreadcrumbItem(folder.getId(), folder.getOriginalName()));

        // 构建路径
        pathBuilder.insert(0, "/" + folder.getOriginalName());

        // 递归处理父文件夹
        if (folder.getParentId() != null) {
            buildFolderPath(userId, folder.getParentId(), breadcrumbs, pathBuilder);
        }
    }

    /**
     * 检查目标文件夹是否是源文件夹的后代
     */
    private boolean isDescendantFolder(Long userId, Long targetFolderId, Long sourceFolderId) {
        if (targetFolderId == null || sourceFolderId == null) {
            return false;
        }

        if (targetFolderId.equals(sourceFolderId)) {
            return true;
        }

        Optional<FileInfo> targetFolderOpt = fileInfoRepository.findByIdAndOwnerIdAndIsDeletedFalse(targetFolderId, userId);
        if (targetFolderOpt.isEmpty() || targetFolderOpt.get().getParentId() == null) {
            return false;
        }

        return isDescendantFolder(userId, targetFolderOpt.get().getParentId(), sourceFolderId);
    }
}
